#include <common.h>
#include <drivers/video.h>
#include <Starflub/Starflub.h>
#include <memory.h>

#define abs(x) (x>0?x:-x);
#define sgn(x) ((x<0)?-1:((x>0)?1:0))

unsigned char *VGA = (unsigned char*)0xA0000;
unsigned char *dbl_buffer;

void init_dbl_buffer() {
	dbl_buffer = (unsigned char*)kmalloc(SCREEN_WIDTH*SCREEN_HEIGHT);
	if(dbl_buffer==0) {
		SFKernelPanic("Not enough memory", "video");
		for(;;);
	}
}

void update_screen() {
	#ifdef VERTICAL_RETRACT
		while((inb(0x3DA)&0x08));
		while(!(inb(0x3DA)&0x08));
	#endif
	memcpy(VGA, dbl_buffer, (unsigned int)(SCREEN_WIDTH*SCREEN_HEIGHT));
}

void setpixel(bitmap_t *bmp, int x, int y, enum MonitorColor color) {
	bmp->data[y*bmp->width+x] = color;
}

void drawrect(bitmap_t *bmp, unsigned short x, unsigned short y, unsigned short x2, unsigned short y2, enum MonitorColor color) {
	unsigned short tx, ty;
	for(ty = y; ty < y2; ty++)
		for(tx = x; tx < x2; tx++)
			setpixel(bmp, tx, ty, color);
}

void draw_bitmap_old(bitmap_t *bmp, int x, int y) {
	int j;
	unsigned int screen_offset = (y<<8)+(y<<6)+x;
	unsigned int bitmap_offset = 0;
	for(j=0; j<bmp->height; j++) {
		memcpy(&dbl_buffer[screen_offset], &bmp->data[bitmap_offset], bmp->width);
		bitmap_offset += bmp->width;
		screen_offset += SCREEN_WIDTH;
	}
}

void line(int x1, int y1, int x2, int y2, enum MonitorColor color)
{
  int i,dx,dy,sdx,sdy,dxabs,dyabs,x,y,px,py;

  dx=x2-x1;      /* the horizontal distance of the line */
  dy=y2-y1;      /* the vertical distance of the line */
  dxabs=abs(dx);
  dyabs=abs(dy);
  sdx=sgn(dx);
  sdy=sgn(dy);
  x=dyabs>>1;
  y=dxabs>>1;
  px=x1;
  py=y1;

  dbl_buffer[(py<<8)+(py<<6)+px]=color;

  if (dxabs>=dyabs) /* the line is more horizontal than vertical */
  {
    for(i=0;i<dxabs;i++)
    {
      y+=dyabs;
      if (y>=dxabs)
      {
        y-=dxabs;
        py+=sdy;
      }
      px+=sdx;
      plot_pixel(px,py,color);
    }
  }
  else /* the line is more vertical than horizontal */
  {
    for(i=0;i<dyabs;i++)
    {
      x+=dxabs;
      if (x>=dyabs)
      {
        x-=dyabs;
        px+=sdx;
      }
      py+=sdy;
      plot_pixel(px,py,color);
    }
  }
}

void polygon(int num_vertices, 
             int *vertices,
             enum MonitorColor color) 
{
  int i;

  for(i=0;i<num_vertices-1;i++)
  {
    line(vertices[(i<<1)+0],
         vertices[(i<<1)+1],
         vertices[(i<<1)+2],
         vertices[(i<<1)+3],
         color);
  }
  line(vertices[0],
       vertices[1],
       vertices[(num_vertices<<1)-2],
       vertices[(num_vertices<<1)-1],
       color);
}

